// Copyright Epic Games, Inc. All Rights Reserved. // 版权声明，Epic Games公司版权所有

#pragma once // 头文件保护宏，确保头文件只被包含一次

#include "Abilities/LyraGameplayAbility.h" // 包含Lyra游戏能力基类头文件
#include "AbilitySystemComponent.h" // 包含虚幻引擎的能力系统组件基类头文件
#include "NativeGameplayTags.h" // 包含原生游戏标签支持头文件

#include "LyraAbilitySystemComponent.generated.h" // 包含UE生成的反射头文件

#define UE_API LYRAGAME_API // 定义宏，用于导出符号到LYRAGAME_API

// 前向声明类，避免包含整个头文件
class AActor; // 前向声明Actor类
class UGameplayAbility; // 前向声明游戏能力类
class ULyraAbilityTagRelationshipMapping; // 前向声明Lyra能力标签关系映射类
class UObject; // 前向声明基础UObject类
struct FFrame; // 前向声明帧结构
struct FGameplayAbilityTargetDataHandle; // 前向声明游戏能力目标数据句柄结构

// 声明游戏标签：能力输入被阻塞，外部定义
LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_AbilityInputBlocked);

/**
 * ULyraAbilitySystemComponent
 * 项目使用的基础能力系统组件类
 * 继承自虚幻引擎的标准能力系统组件，提供Lyra项目的特定功能扩展
 */
UCLASS(MinimalAPI) // UE类声明，MinimalAPI表示只导出必要的符号到模块
class ULyraAbilitySystemComponent : public UAbilitySystemComponent // 继承自UE标准能力系统组件
{
	GENERATED_BODY() // UE生成的宏，用于支持反射系统和序列化

public:

	/**
	 * 构造函数
	 * @param ObjectInitializer - 对象初始化器，用于UE属性系统初始化
	 */
	UE_API ULyraAbilitySystemComponent(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	//~UActorComponent interface
	/**
	 * 结束游戏时的清理操作
	 * @param EndPlayReason - 结束游戏的原因枚举
	 */
	UE_API virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
	//~End of UActorComponent interface

	/**
	 * 初始化能力拥有者和化身角色信息
	 * @param InOwnerActor - 拥有者Actor指针
	 * @param InAvatarActor - 化身Actor指针
	 */
	UE_API virtual void InitAbilityActorInfo(AActor* InOwnerActor, AActor* InAvatarActor) override;

	// 定义函数类型：判断是否应该取消能力
	typedef TFunctionRef<bool(const ULyraGameplayAbility* LyraAbility, FGameplayAbilitySpecHandle Handle)> TShouldCancelAbilityFunc;
	
	/**
	 * 根据函数条件取消能力
	 * @param ShouldCancelFunc - 判断函数，返回true表示应该取消该能力
	 * @param bReplicateCancelAbility - 是否复制取消操作到网络客户端
	 */
	UE_API void CancelAbilitiesByFunc(TShouldCancelAbilityFunc ShouldCancelFunc, bool bReplicateCancelAbility);

	/**
	 * 取消输入激活的能力
	 * @param bReplicateCancelAbility - 是否复制取消操作到网络客户端
	 */
	UE_API void CancelInputActivatedAbilities(bool bReplicateCancelAbility);

	/**
	 * 处理能力输入标签按下
	 * @param InputTag - 输入的游戏标签
	 */
	UE_API void AbilityInputTagPressed(const FGameplayTag& InputTag);

	/**
	 * 处理能力输入标签释放
	 * @param InputTag - 输入的游戏标签
	 */
	UE_API void AbilityInputTagReleased(const FGameplayTag& InputTag);

	/**
	 * 处理能力输入
	 * @param DeltaTime - 帧时间差
	 * @param bGamePaused - 游戏是否暂停
	 */
	UE_API void ProcessAbilityInput(float DeltaTime, bool bGamePaused);

	/**
	 * 清除能力输入状态
	 */
	UE_API void ClearAbilityInput();

	/**
	 * 检查激活组是否被阻塞
	 * @param Group - 激活组枚举
	 * @return bool - 返回该组是否被阻塞
	 */
	UE_API bool IsActivationGroupBlocked(ELyraAbilityActivationGroup Group) const;

	/**
	 * 添加能力到激活组
	 * @param Group - 激活组枚举
	 * @param LyraAbility - Lyra能力指针
	 */
	UE_API void AddAbilityToActivationGroup(ELyraAbilityActivationGroup Group, ULyraGameplayAbility* LyraAbility);

	/**
	 * 从激活组移除能力
	 * @param Group - 激活组枚举
	 * @param LyraAbility - Lyra能力指针
	 */
	UE_API void RemoveAbilityFromActivationGroup(ELyraAbilityActivationGroup Group, ULyraGameplayAbility* LyraAbility);

	/**
	 * 取消激活组中的能力
	 * @param Group - 激活组枚举
	 * @param IgnoreLyraAbility - 要忽略的Lyra能力指针
	 * @param bReplicateCancelAbility - 是否复制取消操作到网络客户端
	 */
	UE_API void CancelActivationGroupAbilities(ELyraAbilityActivationGroup Group, ULyraGameplayAbility* IgnoreLyraAbility, bool bReplicateCancelAbility);

	/**
	 * 使用游戏效果添加指定的动态授予标签
	 * @param Tag - 要添加的游戏标签
	 */
	UE_API void AddDynamicTagGameplayEffect(const FGameplayTag& Tag);

	/**
	 * 移除用于添加指定动态授予标签的所有活跃游戏效果实例
	 * @param Tag - 要移除的游戏标签
	 */
	UE_API void RemoveDynamicTagGameplayEffect(const FGameplayTag& Tag);

	/**
	 * 获取与给定能力句柄和激活信息相关的能力目标数据
	 * @param AbilityHandle - 能力规格句柄
	 * @param ActivationInfo - 能力激活信息
	 * @param OutTargetDataHandle - 输出的目标数据句柄
	 */
	UE_API void GetAbilityTargetData(const FGameplayAbilitySpecHandle AbilityHandle, FGameplayAbilityActivationInfo ActivationInfo, FGameplayAbilityTargetDataHandle& OutTargetDataHandle);

	/**
	 * 设置当前的标签关系映射，如果为null则清除
	 * @param NewMapping - 新的标签关系映射对象指针
	 */
	UE_API void SetTagRelationshipMapping(ULyraAbilityTagRelationshipMapping* NewMapping);
	
	/**
	 * 查看能力标签并收集额外的需求和阻塞标签
	 * @param AbilityTags - 能力标签容器
	 * @param OutActivationRequired - 输出的激活需求标签容器
	 * @param OutActivationBlocked - 输出的激活阻塞标签容器
	 */
	UE_API void GetAdditionalActivationTagRequirements(const FGameplayTagContainer& AbilityTags, FGameplayTagContainer& OutActivationRequired, FGameplayTagContainer& OutActivationBlocked) const;

	/**
	 * 尝试在生成时激活能力
	 */
	UE_API void TryActivateAbilitiesOnSpawn();

protected:

	/**
	 * 能力规格输入按下处理
	 * @param Spec - 能力规格引用
	 */
	UE_API virtual void AbilitySpecInputPressed(FGameplayAbilitySpec& Spec) override;

	/**
	 * 能力规格输入释放处理
	 * @param Spec - 能力规格引用
	 */
	UE_API virtual void AbilitySpecInputReleased(FGameplayAbilitySpec& Spec) override;

	/**
	 * 通知能力激活
	 * @param Handle - 能力规格句柄
	 * @param Ability - 游戏能力指针
	 */
	UE_API virtual void NotifyAbilityActivated(const FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability) override;

	/**
	 * 通知能力激活失败
	 * @param Handle - 能力规格句柄
	 * @param Ability - 游戏能力指针
	 * @param FailureReason - 失败原因标签容器
	 */
	UE_API virtual void NotifyAbilityFailed(const FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason) override;

	/**
	 * 通知能力结束
	 * @param Handle - 能力规格句柄
	 * @param Ability - 游戏能力指针
	 * @param bWasCancelled - 是否被取消
	 */
	UE_API virtual void NotifyAbilityEnded(FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability, bool bWasCancelled) override;

	/**
	 * 应用能力阻塞和取消标签
	 * @param AbilityTags - 能力标签容器
	 * @param RequestingAbility - 请求能力指针
	 * @param bEnableBlockTags - 是否启用阻塞标签
	 * @param BlockTags - 阻塞标签容器
	 * @param bExecuteCancelTags - 是否执行取消标签
	 * @param CancelTags - 取消标签容器
	 */
	UE_API virtual void ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bEnableBlockTags, const FGameplayTagContainer& BlockTags, bool bExecuteCancelTags, const FGameplayTagContainer& CancelTags) override;

	/**
	 * 处理能力可取消状态变化
	 * @param AbilityTags - 能力标签容器
	 * @param RequestingAbility - 请求能力指针
	 * @param bCanBeCanceled - 是否可被取消
	 */
	UE_API virtual void HandleChangeAbilityCanBeCanceled(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bCanBeCanceled) override;

	/**
	 * 通知客户端能力激活失败
	 * @param Ability - 游戏能力指针
	 * @param FailureReason - 失败原因标签容器
	 */
	UFUNCTION(Client, Unreliable) // 客户端RPC，不可靠传输
	UE_API void ClientNotifyAbilityFailed(const UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason);

	/**
	 * 处理能力失败
	 * @param Ability - 游戏能力指针
	 * @param FailureReason - 失败原因标签容器
	 */
	UE_API void HandleAbilityFailed(const UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason);

protected:
	
	UPROPERTY() 
	TObjectPtr<ULyraAbilityTagRelationshipMapping> TagRelationshipMapping; // 标签关系映射对象指针
	
	TArray<FGameplayAbilitySpecHandle> InputPressedSpecHandles; // 存储输入按下的能力规格句柄数组
	
	TArray<FGameplayAbilitySpecHandle> InputReleasedSpecHandles; // 存储输入释放的能力规格句柄数组
	
	TArray<FGameplayAbilitySpecHandle> InputHeldSpecHandles; // 存储输入按住的能力规格句柄数组
	
	int32 ActivationGroupCounts[(uint8)ELyraAbilityActivationGroup::MAX]; // 激活组计数数组，大小为ELyraAbilityActivationGroup枚举的最大值
};

#undef UE_API // 取消宏定义，避免污染其他代码